#include <linux/device.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include "esp_wifi.h"

#define SPI_BUF_SIZE 2048
#define SPI_CNT 1
#define SPI_NAME "spi_serial"
#define TEST_N 129


static int esp_gpio_hand = -1;


volatile u8 data_path = 0;
static struct esp_spi_context spi_context;

 
struct sk_buff* read_packet(struct esp_adapter *adapter)
{
	struct esp_spi_context *context;
	struct sk_buff* skp = NULL;

	if(!adapter || !adapter->if_context)
	{
		printk (KERN_ERR "%s: Invalid args\n", __func__);
		return NULL;
	}

	context = adapter->if_context;

	if(context->esp_spi_dev)
	{
		skp = skb_dequeue(&(context->rx_q));
	} else {
		printk (KERN_ERR "%s: Invalid args\n", __func__);
		return NULL;
	}

	return skp;
}

int write_packet(struct esp_adapter *adapter, u8 *buf, u32 size)
{
	struct esp_spi_context *context;
	struct sk_buff* skp = NULL;
	int ret = -EAGAIN;
	u8 *tx_buf = NULL;

	if(!adapter || !buf || size == 0 || !adapter->if_context || size > SPI_BUF_SIZE)
	{
		printk (KERN_ERR "%s: Invalid args\n", __func__);
		return ret;
	}

	/* Adjust length to make it multiple of 4 bytes  */
	size += 4 - (size & 3);

	context = adapter->if_context;

	skp =  esp_alloc_skb(size);

	if(IS_ERR(skp))
		return ret;

	tx_buf = skb_put(skp, size);

	if (!tx_buf) {
		dev_kfree_skb(skp);
		ret = -ENOMEM;
		return ret;
	}
	
	memcpy(tx_buf, buf, size); //There may be an issue

	/* Enqueue SKB in tx_q */
	skb_queue_tail(&spi_context.tx_q, skp);

	if (spi_context.spi_workqueue)
	queue_work(spi_context.spi_workqueue, &spi_context.spi_work);
	ret = ESP_OK;
	return ret;
}

static struct esp_if_ops if_ops = {
	.write = write_packet,
	.read = read_packet,
};

static int process_rx_buf(struct sk_buff *skb)
{
	struct esp_payload_header *header;
	u16 offset = 0;
	u16 len = 0;
	
	if(skb == NULL)
	{
		return -EINVAL;
	}
	
	header = (struct esp_payload_header *) skb->data;
	
	offset = le16_to_cpu(header->offset);

	if(header->if_type == 0xF)
	{
		// printk("This is an empty package\n");
		return -EINVAL;
	}
	
	if(offset != sizeof(struct esp_payload_header))
	{
		return -EINVAL;
	}

	len = le16_to_cpu(header->len);
	if (len == 0)
		return -EINVAL;
	// printk("len = [%d]\n", len);

	// printk("offset = [%d] len - [%d]\n", offset, len);
	len += sizeof(struct esp_payload_header);
	if(len > SPI_BUF_SIZE)
	{
		return -EINVAL;
	}


	skb_trim(skb, len);

	if(header->if_type == ESP_PRIV_IF)
	{
		//do nothing
		return 0; 
	}

	skb_queue_tail(&spi_context.rx_q, skb);

	esp_process_new_packet_intr(spi_context.adapter);
	return 0;
}

static void esp_spi_work(struct work_struct *work)  
{  
    int ret = -1;   
    struct spi_transfer tm;  
    struct spi_transfer *t = &tm;  

    static struct sk_buff *tx_skp_static = NULL;  
    static unsigned char *tx_buf = NULL;

    struct sk_buff *tx_skp = NULL;  
    struct sk_buff *rx_skp = NULL;   
    unsigned char *rx_buf = NULL;
	struct esp_payload_header *header = NULL;
	unsigned int paloadlen = sizeof(struct esp_payload_header);
	static int a = 0;


	memset(t, 0x0, sizeof(struct spi_transfer)); 

    // 初始化tx_skp_static  
    if (tx_skp_static == NULL) {  
        tx_skp_static = esp_alloc_skb(SPI_BUF_SIZE);  
        if (tx_skp_static == NULL) {  
            printk(KERN_ERR "Fail to allocate tx_skp_static\n");  
            return;  
        }  

        tx_buf = skb_put(tx_skp_static, SPI_BUF_SIZE);   

        memset(tx_buf, 0, SPI_BUF_SIZE);
		header = (struct esp_payload_header *)tx_buf;
		header->if_type = ESP_NULL;
		header->offset = cpu_to_le16(sizeof(struct esp_payload_header));
		header->len = 0;
		
        // memcpy(tx_buf + paloadlen, "hello world esp", 16); 
    }  

    // 从队列中获取 tx_skp  
    if (!skb_queue_empty(&spi_context.tx_q)) { 
        tx_skp = skb_dequeue(&spi_context.tx_q);  
    }  

    // 选择要发送的数据  
    if (tx_skp != NULL) {  
        t->tx_buf = (void *)tx_skp->data; // 要发送的数据  
		// print_hex_dump_bytes("Tx:", DUMP_PREFIX_NONE, tx_skp->data + 8, tx_skp->len - 8);
    } else {
		if(tx_buf)
		{
			sprintf(tx_buf + paloadlen, "hello world esp%d", a++);
			t->tx_buf = tx_buf; // 使用静态分配的缓冲区  
		}
    }  

    // 初始化接收缓冲区  
    rx_skp = esp_alloc_skb(SPI_BUF_SIZE);  
    if (rx_skp == NULL) {  
        printk(KERN_ERR "Fail to allocate rx_skp\n");  
        return;  
    }  
    rx_buf = skb_put(rx_skp, SPI_BUF_SIZE); 

    memset(rx_buf, 0, SPI_BUF_SIZE);  

    // 设置传输参数  
    t->rx_buf = rx_buf;  
    t->len = SPI_BUF_SIZE;  

    // 检查有效的传输长度  
    if (t->len <= 0 || !t->tx_buf || !t->rx_buf) {  
        printk(KERN_ERR "Invalid transfer parameters: len=%d, tx_buf=%p, rx_buf=%p\n", t->len, t->tx_buf, t->rx_buf);  
        dev_kfree_skb(rx_skp); // 释放接收缓冲区  
        return;  
    }  
 
	ret = spi_sync_transfer(spi_context.esp_spi_dev, t, 1);
    if (ret) {  
        printk(KERN_ERR "SPI transmission failed with error: %d\n", ret);  
        dev_kfree_skb(rx_skp); // 释放接收缓冲区  
        return; // 直接返回错误码  
    }  
    // 打印接收到的数据
	if(process_rx_buf(rx_skp) != 0) //recv spi data Not 0 failed
	{
    	dev_kfree_skb(rx_skp); // 释放接收缓冲区  
	}

    if (tx_skp) {//After sending successfully, the data can be clear
        dev_kfree_skb(tx_skp); // 释放发送缓冲区  
    }  
}


// static void esp_spi_work(struct work_struct *work)  
// {  
//     int ret = -1;  
//     unsigned char *tx_data;  // 发送数据缓冲区指针  
//     unsigned char *rxdata;   // 接收数据缓冲区指针  
//     size_t data_length = 128; // 数据长度  
//     struct spi_message m;  
//     struct spi_transfer tm;  
//     struct spi_transfer *t = &tm;  

//     // 动态分配发送和接收数据的缓冲区  
//     tx_data = kmalloc(data_length, GFP_KERNEL);  
//     if (!tx_data) {  
//         printk(KERN_ERR "Failed to allocate memory for tx_data\n");  
//         return;  
//     }  

//     rxdata = kmalloc(data_length, GFP_KERNEL);  
//     if (!rxdata) {  
//         printk(KERN_ERR "Failed to allocate memory for rxdata\n");  
//         kfree(tx_data); // 释放已分配的 tx_data  
//         return;  
//     }  

//     // 初始化发送数据  
//     memcpy(tx_data, "hello world\n", 13); // 复制数据到发送缓冲区  
//     memset(rxdata, 0, data_length); // 清空接收缓冲区  

//     printk("Entering spi_communication\n");  

//     // 初始化 SPI 传输结构  
//     memset(t, 0, sizeof(struct spi_transfer)); 

//     t->tx_buf = tx_data;  
//     t->rx_buf = rxdata;  
//     t->len = 128; // 使用实际数据长度  

//     // 日志信息  
//     spi_message_init(&m);  
//     spi_message_add_tail(t, &m);   

//     // 执行 SPI 同步操作  
//     ret = spi_sync(spi_context.esp_spi_dev, &m);  
//     if (ret) {  
//         printk(KERN_ERR "SPI transmission failed with error: %d\n", ret);  
//     } else {  
//         printk("recv buf = {%s}\n", rxdata);  
//     }  

//     // 释放动态分配的内存  
//     kfree(tx_data);  
//     kfree(rxdata);  
// }

// static void esp_spi_work(struct work_struct *work)
// {
// 	int ret = -1;  
//     unsigned char tx_data[128] = "hello world\n"; // 发送数据  
//     unsigned char rxdata[128] = {0};      // 接收数据  
//     struct spi_message m;  
//     struct spi_transfer tm;  
//     struct spi_transfer *t = &tm;  
//     printk("Entering spi_communication\n");  

//     // 初始化 SPI 传输结构  
//     memset(t, 0, sizeof(struct spi_transfer));   
//     t->tx_buf = tx_data;  
//     t->rx_buf = rxdata;  

//     // 使用 len 直接设置长度  
//     t->len = 128; // 确保 len 是合理的  

//     // 日志信息  
//     spi_message_init(&m);  
//     spi_message_add_tail(t, &m);   

//     // 执行 SPI 同步操作  
//     ret = spi_sync(spi_context.esp_spi_dev, &m);  
//     if (ret) {  
//         printk(KERN_ERR "SPI transmission failed with error: %d\n", ret);  
//         return ret; // 直接返回错误码  
//     }  

//     printk("recv buf = {%s}\n", rxdata);  
// }

static irqreturn_t spi_interrupt_handler(int irq, void * dev)
{
	/* ESP32 is ready for next transaction */
	// printk("irqreturn_t spi_interrupt_handler(int irq, void * dev)\n");
	if (spi_context.spi_workqueue)
		queue_work(spi_context.spi_workqueue, &spi_context.spi_work);

	return IRQ_HANDLED;
}

int spi_open_opt(struct inode * nodep, struct file * filep)
{
	filep->private_data = &spi_context; /* 设置私有数据 */
	return 0;
}

static int spi_communication(struct file *filep, void *buf, int len)  
{  
    int ret = -1;  
    unsigned char *tx_data = buf; // 发送数据  
    unsigned char rxdata[128] = {0};      // 接收数据  
    struct spi_message m;  
    struct spi_transfer tm;  
    struct spi_transfer *t = &tm;  
	struct esp_spi_context *spi_con = NULL;

    // 检查文件指针和 SPI 上下文的有效性  
    if (filep == NULL) {  
        printk(KERN_ERR "Invalid file pointer\n");  
        return -EINVAL;  
    }  

    spi_con = (struct esp_spi_context *)filep->private_data;  
    if (spi_con == NULL) {  
        printk(KERN_ERR "spi_con is NULL\n");  
        return -EINVAL;   
    }  

    if (spi_con->esp_spi_dev == NULL) {  
        printk(KERN_ERR "spi_con->esp_spi_dev is NULL\n");  
        return -EINVAL;   
    }  

    printk("Entering spi_communication\n");  

    // 初始化 SPI 传输结构  
    memset(t, 0, sizeof(struct spi_transfer));   
    t->tx_buf = tx_data;  
    t->rx_buf = rxdata;  

    // 使用 len 直接设置长度  
    t->len = len; // 确保 len 是合理的  

    // 日志信息  
    spi_message_init(&m);  
    spi_message_add_tail(t, &m);   

    // 执行 SPI 同步操作  
    ret = spi_sync(spi_con->esp_spi_dev, &m);  
    if (ret) {  
        printk(KERN_ERR "SPI transmission failed with error: %d\n", ret);  
        return ret; // 直接返回错误码  
    }  

    // 检查 buf 是否有效并复制接收到的数据  
    if (buf != NULL && len > 0 && len <= sizeof(rxdata)) {  
        memcpy(buf, rxdata, len);   
        printk("Data copied to user buffer\n");  
    } else {  
        printk(KERN_ERR "Invalid buffer or length\n");  
        return -EINVAL;   
    }  

    printk("recv buf = {%s}\n", rxdata);  
    return 0; // 更改返回值，表示成功  
}
ssize_t spi_read_opt(struct file * filep, char __user *bufp, size_t size, loff_t *offset)
{
	long err = -1;
	char buf[TEST_N] = {0};
	spi_communication(filep, buf, TEST_N);
	err = copy_to_user(bufp, buf, sizeof(buf));

	return 0;
}

ssize_t spi_write_opt(struct file *filep, const char __user *bufp, size_t size, loff_t *offset)  
{  
    // char buf[TEST_N] = {0};  
    // long err = -1;  

    // // 安全性检查：确保 bufp 指针有效并且 size 不超过 TEST_N  
    // if (!bufp || size > TEST_N) {  
    //     printk(KERN_ERR "Invalid parameters: bufp is NULL or size exceeds buffer limit\n");  
    //     return -EINVAL; // 返回无效参数错误码  
    // }  

    // // 从用户空间拷贝数据  
    // if (copy_from_user(buf, bufp, size)) {  
    //     printk(KERN_ERR "Failed to copy data from user\n");  
    //     return -EFAULT; // 返回拷贝失败错误  
    // }  

    // printk(KERN_ALERT "bufp = [%s]\n", buf);  

    // // 根据 GPIO 值判断是否进行 SPI 通信  
    // if (gpio_get_value(esp_gpio_hand)) {  
    //     // 使用 buf 作为发送数据  
    //     err = spi_communication(filep, buf, size);  
    //     if (err < 0) {  
    //         printk(KERN_ERR "SPI communication failed with error: %ld\n", err);  
    //         return err; // 返回 SPI 通信的错误码  
    //     }  
    // }  

    // printk(KERN_ALERT "spi_write = [%s]\n", buf);  
	if (spi_context.spi_workqueue)
		queue_work(spi_context.spi_workqueue, &spi_context.spi_work);

    return size; // 返回实际写入的字节数  
}

long spi_ioctl_opt(struct file *filep, unsigned int cmd, unsigned long arg)
{
	switch(cmd){
		case 1:
			break; 
		case 2:
			break; 
	  
		default: 
			break;
	}

	return 0;
}

int spi_release_opt(struct inode *nodep, struct file *filep)
{
	// // Delete device
	// cdev_del(&spi_context.spi_dev.cdev);
	// unregister_chrdev_region(spi_context.spi_dev.devid, SPI_CNT);

	// // Cancel classes and devices
	// device_destroy(spi_context.spi_dev.class, spi_context.spi_dev.devid);
	// class_destroy(spi_context.spi_dev.class);
	return 0;
}
/* SPI operation structure */
static const struct file_operations spi_file_ops = {

	.owner = THIS_MODULE,

	.open = spi_open_opt,

	.read = spi_read_opt,

	.write = spi_write_opt,
	
	.unlocked_ioctl = spi_ioctl_opt,

	.release = spi_release_opt,
};

static int esp32_probe(struct spi_device *spi)
{
	int status;
	
	struct device_node *nd; /* 设备节点 */

	printk(" esp32_probe(struct spi_device *spi)\n");

	
	/*初始化spi_device */
	spi->mode = SPI_MODE_0;	/*MODE0，CPOL=0，CPHA=0*/
	spi_setup(spi);

	spi_context.esp_spi_dev = spi;
	printk("spi = [%p]\n", spi);
	nd = of_find_node_by_path("/esp32handshake");

	if(nd == NULL) {
		printk("gpioled node cant not found!\r\n");
	return -EINVAL;
	} else {
		printk("gpioled node has been found!\r\n");
	}

	esp_gpio_hand = of_get_named_gpio(nd, "led-gpios", 0);
	if(esp_gpio_hand < 0)
	{
		printk (KERN_ERR "Failed to of_get_named_gpio esp_gpio_hand[%d]\n", esp_gpio_hand);
		goto error;
	}

	printk("esp_gpio_hand = %d\n", esp_gpio_hand);

	status = gpio_request(esp_gpio_hand, "SPI_HANDSHAKE_PIN");
	if (status) {
		printk (KERN_ERR "Failed to obtain GPIO");
		goto error;
	}

	status = gpio_direction_input(esp_gpio_hand);

	if (status) {
		printk (KERN_ERR "Failed to set GPIO direction");
		goto error;
	}

	
	status = request_irq(gpio_to_irq(esp_gpio_hand), spi_interrupt_handler,
		IRQF_SHARED | IRQF_TRIGGER_RISING,
		"ESP_SPI", spi);

	if (status) {
		printk (KERN_ERR "Failed to request IRQ");
		goto error;
	}

	// 1.Create device number
	if(spi_context.spi_dev.major)
	{
		spi_context.spi_dev.devid = MKDEV(spi_context.spi_dev.major, 0);
		register_chrdev_region(spi_context.spi_dev.devid, SPI_CNT, SPI_NAME);
	}else{
		alloc_chrdev_region(&spi_context.spi_dev.devid, 0, SPI_CNT,
			SPI_NAME);
		spi_context.spi_dev.major = MAJOR(spi_context.spi_dev.devid);
	}

	// 2.Register Device
	cdev_init(&spi_context.spi_dev.cdev, &spi_file_ops);
	cdev_add(&spi_context.spi_dev.cdev, spi_context.spi_dev.devid, SPI_CNT);

	// 3.Create Class
	spi_context.spi_dev.class = class_create(THIS_MODULE, SPI_NAME);
	if(IS_ERR(spi_context.spi_dev.class))
	{
		return PTR_ERR(spi_context.spi_dev.class);
	}

	// 4.Create device
	spi_context.spi_dev.device = device_create(spi_context.spi_dev.class, NULL, spi_context.spi_dev.devid, NULL, SPI_NAME);
	
error:

	return 0;
}

static int esp32_remove(struct spi_device *spi)
{
	// Delete device
	cdev_del(&spi_context.spi_dev.cdev);
	unregister_chrdev_region(spi_context.spi_dev.devid, SPI_CNT);

	// Cancel classes and devices
	device_destroy(spi_context.spi_dev.class, spi_context.spi_dev.devid);
	class_destroy(spi_context.spi_dev.class);

	disable_irq(gpio_to_irq(esp_gpio_hand));
	free_irq(gpio_to_irq(esp_gpio_hand), spi);

	gpio_free(esp_gpio_hand);
	return 0;
}

/* 传统匹配方式ID列表 */
static const struct spi_device_id esp32_id[] = {
	{"alientek,esp32", 0},  
	{}
};

/* 设备树匹配列表 */
static const struct of_device_id esp32_of_match[] = {
	{ .compatible = "alientek,esp32" },
	{ /* Sentinel */ }
};


static struct spi_driver esp32_driver = {
	.probe = esp32_probe,
	.remove = esp32_remove,
	.driver = {
		.owner = THIS_MODULE,
		.name = "esp32",
		.of_match_table = esp32_of_match, 
	},
	.id_table = esp32_id,
};

static void spi_exit(void)
{
	msleep(200);

	skb_queue_purge(&spi_context.tx_q);
	skb_queue_purge(&spi_context.rx_q);

	spi_unregister_driver(&esp32_driver);

	if (spi_context.spi_workqueue) {
		destroy_workqueue(spi_context.spi_workqueue);
		spi_context.spi_workqueue = NULL;
	}

	esp_remove_card(spi_context.adapter);


	memset(&spi_context, 0, sizeof(spi_context));
	
}

static int spi_init(void)
{
	int status = -EAGAIN;
	// struct spi_master *master = NULL;
	
	// initialize spi device
	status = spi_register_driver(&esp32_driver);
	if(status)
	{
		printk (KERN_ERR "Failed to spi register driver\n");
		goto error;
	}

	// initialize sk_buff queue and work queue
	spi_context.spi_workqueue = create_workqueue("ESP_SPI_WORK_QUEUE");

	if (!spi_context.spi_workqueue) {
		printk (KERN_ERR "Failed to create spi_workqueue\n");
		goto error;
	}

	INIT_WORK(&spi_context.spi_work, esp_spi_work);

	skb_queue_head_init(&spi_context.tx_q);
	skb_queue_head_init(&spi_context.rx_q);

	//initialize network device
	status = esp_add_card(spi_context.adapter);
	if (status) {
		printk (KERN_ERR "Failed to add card\n");
		goto error;
	}

	msleep(200);

	status = ESP_OK;
	// while (1)
	// {
	// 	ssleep(1);
	// 	if (spi_context.spi_workqueue)
	// 		queue_work(spi_context.spi_workqueue, &spi_context.spi_work);
	// }
	
	return status;

error:
	status = ESP_NO;
	spi_exit();
	return status;
}

int esp_init_interface_layer(struct esp_adapter *adapter)
{
	if (!adapter)
		return -EINVAL;

	memset(&spi_context, 0, sizeof(spi_context));

	adapter->if_context = &spi_context;
	adapter->if_ops = &if_ops;
	adapter->if_type = ESP_IF_TYPE_SPI;
	spi_context.adapter = adapter;

	return spi_init();
}
void esp_deinit_interface_layer(void)
{
	spi_exit();
}